﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace YouTubeStormer
{
    class LoginRelated
    {
        Communications communications;
        public Account CurrentlyLoggedIn = new Account();

        public class Account
        {
            public string Username { get; set; }
            public string Password { get; set; }
            public Communications.ProxyInfo Proxy { get; set; }
        }

        public LoginRelated(Communications communications)
        {
            this.communications = communications;
        }

        bool AccountAlreadyVoted(string commentID, string username)
        {
            return Properties.Settings.Default.AccountVoteLog.Contains(commentID + ":" + username);
        }

        public void LogAccountVote(string commentID, string username)
        {
            Properties.Settings.Default.AccountVoteLog.Add(commentID + ":" + username);
            Properties.Settings.Default.Save();
        }

        public Account[] FindAvailableAccountsForVote(string commentID)
        {
            if (!AccountAlreadyVoted(commentID, CurrentlyLoggedIn.Username))
                return new Account[] { CurrentlyLoggedIn };

            var availableAccounts = new List<Account>();
            foreach (string accountString in Properties.Settings.Default.Accounts)
            {
                var account = ParseAccount(accountString);
                if (!Properties.Settings.Default.AccountVoteLog.Contains(commentID + ":" + account.Username)) 
                    availableAccounts.Add(account);
            }

            if (availableAccounts.Count > 0)
                return availableAccounts.ToArray();
            else
                return null;

        }

        public Account ParseAccount(string accountLine)
        {
            var accountParts = accountLine.Split(':');
            return new LoginRelated.Account { Username = accountParts[0], Password = accountParts[1], Proxy = new Communications.ProxyInfo { IP = accountParts[2], Port = accountParts[3], Username = accountParts[4], Password = accountParts[5] } };
        }

        public bool PerformLogin(out Main.DebugDataHelper debugData, Account account)
        {
            debugData = new Main.DebugDataHelper();

            communications.ClearCookies();

            communications.Proxy = account.Proxy;

            string ResponseData = communications.PerformGet(Communications.YoutubePreAuthenticationUrl);

            if (ResponseData == null)
            {
                debugData.Output = "proxyfail";
                return false;
            }

            string GALX = Regex.Match(ResponseData, "name=\"GALX\"[\\s]*value=\"([a-zA-Z0-9-_\\.]*)\"").Groups[1].ToString();
            string dsh = Regex.Match(ResponseData, "id=\"dsh\"[\\s]*value=\"([a-zA-Z0-9-_\\.]*)\"").Groups[1].ToString();
            string uilel = Regex.Match(ResponseData, "id=\"uilel\"[\\s]*value=\"([a-zA-Z0-9-_\\.]*)\"").Groups[1].ToString();

            var postData = new Communications.PostData();
            postData.AddValue("ltmpl", "sso");
            postData.AddValue("continue", Communications.YoutubeAuthContinueUrl);
            postData.AddValue("service", "youtube");
            postData.AddValue("uilel", uilel);
            postData.AddValue("dsh", dsh);
            postData.AddValue("hl", "en_US");
            postData.AddValue("GALX", GALX);
            postData.AddValue("Email", account.Username);
            postData.AddValue("Passwd", account.Password);
            postData.AddValue("PersistentCookie", "yes");
            postData.AddValue("rmShown", "1");
            postData.AddValue("signIn", "Sign in");
            postData.AddValue("asts", "");
            debugData.Input = postData.ToString();

            communications.PerformPost(Communications.YoutubeAuthenticationUrl, postData, Communications.YoutubePreAuthenticationUrl);
            ResponseData = communications.PerformGet(Communications.YoutubeCheckCookieUrl, referer: Communications.YoutubeAuthenticationUrl);
            debugData.Output = ResponseData;
            string authID = Regex.Split(Regex.Split(ResponseData, "auth=")[1], "&#39;")[0];
            communications.PerformGet(Communications.YoutubeLoginAuthorizationUrl + authID); ;

            if (ResponseData.Contains("<title>Redirecting</title>"))
            {
                CurrentlyLoggedIn = account;
                return true;
            }
            else
            {
                CurrentlyLoggedIn = new Account();
                return false;
            }
        }
    }
}
